package flib;

import java.io.File;
import java.util.Vector;

import javax.swing.JFileChooser;

import blobDetector.Blob;
import blobDetector.BlobDetector;

import simpleGeom.DepthAnalyser2D;
import processing.core.PApplet;
import processing.core.PGraphics;
import processing.core.PImage;
import simpleGeom.Polygon2D;

public class PixelFloorApplet extends PApplet {
	PImage imgFloorplan;
	float[][] gridBrightness;
	Object[][] areas;
	float treshhold=100;
	float[][]gridAnalyse;
	int nX;
	int nY;
	final static int BLACK=0;
	final static int WHITE=255;
	final static int BORDER=255;
	Pixel[][] grid;
	Vector<Pixel>outside;
	Vector<Blob>blobs;
	Vector<Blob>roomBlobs;
	PGraphics roomblobsGraphics;
	float[][]border;
	String pathImage="/Users/administrator/projekte/Doktor/work/Floorplans/b1p031i77f0n210.jpg";
	
	public void setup(){
		size(1200,800,P2D);
		
		imgFloorplan=this.loadImage(pathImage);
		setupPlan();
		
		
		
		
	}
	float[][]rooms;
	float[][]invert;
	public float[][] shrinkBlackDist(float[][] input,float dist){
		
		float[][] blackDist=DepthAnalyser2D.getDepth(input);
		for (int x=0;x<nX;x++){
			for (int y=0;y<nY;y++){
				float d=blackDist[x][y];
				if (blackDist[x][y]>dist){
					blackDist[x][y]=0;
				}
				else{
					blackDist[x][y]=255;
				}
			}
		}
		return blackDist;
	}
	public void collectBorders(){
		border=new float[nX][nY];
		Vector<Pixel>candidates=new Vector<Pixel>();
		for (int x=0;x<nX;x++){
			for (int y=0;y<nY;y+=nY-1){
			Pixel p=grid[x][y];
			
				candidates.add(p);
			
			}
		}
		for (int y=0;y<nY;y++){
			for (int x=0;x<nX;x+=nX-1){
			Pixel p=grid[x][y];
			
				candidates.add(p);
			
			}
		}
		outside=reach(candidates,100);
		for (int i=0;i<outside.size();i++){
			Pixel p=outside.get(i);
			border[p.x][p.y]=BORDER;
		}
	}
	
	// depth shrink.
	// depth grow.
	public Vector<Pixel> reach(Vector<Pixel>candidates,float iso){
		Vector<Pixel>reached=new Vector<Pixel>();
		for (int i=0;i<candidates.size();i++){
			Pixel pixel=candidates.get(i);
			pixel.checked=true;
			reached.add(pixel);
		}
		
		while (candidates.size()>0){
			Vector<Pixel>nextCandidates=new Vector<Pixel>();
			for (int i=0;i<candidates.size();i++){
				Pixel pixel=candidates.get(i);
				int x=pixel.x;
				int y=pixel.y;
				int x1=max(x-1,0);
				int y1=max(y-1,0);
				int x2=min(nX,x+2);
				int y2=min(nY,y+2);
				for (int cX=x1;cX<x2;cX++){
					for (int cY=y1;cY<y2;cY++){
						Pixel nb=grid[cX][cY];
						if (!nb.checked&&nb.brightness>iso){
							nb.checked=true;
							nextCandidates.add(nb);
							reached.add(nb);
						}
					}
				}
				
			}
			candidates=nextCandidates;
		}
		return reached;
	}
	public void setupPlan(){
		
		nX=imgFloorplan.width;
		nY=imgFloorplan.height;
		roomblobsGraphics=createGraphics(nX, nY, P2D);
		gridBrightness=new float[nX][nY];
		grid=new Pixel[nX][nY];
		for (int x=0;x<nX;x++){
			for (int y=0;y<nY;y++){
				if(x==0||x==nX-1||y==0||y==nY-1){
					imgFloorplan.set(x, y,color(255));
				}
			}
		}
		
	//	imgFloorplan.updatePixels();
		for (int x=0;x<nX;x++){
			for (int y=0;y<nY;y++){
				int col=imgFloorplan.get(x, y);
				float br=brightness(col);
				Pixel pixel=new Pixel(x,y);
				pixel.brightness=br;
				grid[x][y]=pixel;
				gridBrightness[x][y]=br;
			}
		}
		collectBorders();
		float[][] black=new float[nX][nY];
		for (int x=0;x<nX;x++){
			for (int y=0;y<nY;y++){
				int col=imgFloorplan.get(x, y);
				float br=brightness(col);
				if (br>100)
					black[x][y]=0;
				else{
					black[x][y]=1000;
				}
			}
		}
		gridAnalyse=shrinkBlackDist(black,3);
		invert=new float[nX][nY];
		for (int x=0;x<gridAnalyse.length;x++){
			for (int y=0;y<gridAnalyse[0].length;y++){
				if (gridAnalyse[x][y]==0){
					invert[x][y]=0;
				}
				else{
					invert[x][y]=1000;
				}
			}
		}
		invert=shrinkBlackDist(invert,3);
		
		BlobDetector bD=new BlobDetector(nX,nY);
		bD.setValues(invert);
		bD.calculateBlobs(100);
		blobs=bD.getBlobs();
		
		println("blobs"+blobs.size());
		for (int i=0;i<blobs.size();i++){
			Blob blob=blobs.get(i);
			if (abs(Polygon2D.getArea(blob.getBorders()))<200){
				fill(0,0,255);
				for (int x=blob.getMinX();x<blob.getMaxX();x++){
					for (int y=blob.getMinY();y<blob.getMaxY();y++){
						if (Polygon2D.contains(x, y, blob.getBorders())){
							invert[x][y]=0;
						}
					}
				}
			}
		}
		
		rooms=new float[nX][nY];
		for (int x=0;x<nX;x++){
			for (int y=0;y<nY;y++){
				if (invert[x][y]==0){
					rooms[x][y]=1000;
				}
				else{
					rooms[x][y]=0;
				}
			}
		}
		rooms=shrinkBlackDist(rooms,60);
		for (int x=0;x<nX;x++){
			for (int y=0;y<nY;y++){
				if (rooms[x][y]==0){
					rooms[x][y]=0;
				}
				else{
					rooms[x][y]=1000;
				}
			}
		}
		rooms=shrinkBlackDist(rooms,50);
		for (int x=0;x<nX;x++){
			for (int y=0;y<nY;y++){
				if (rooms[x][y]==0){
					rooms[x][y]=1000;
				}
				else{
					rooms[x][y]=0;
				}
				if (invert[x][y]==255){
					rooms[x][y]=0;
				}
				
			}
		}
		bD.setValues(rooms);
		bD.calculateBlobs(1);
		roomBlobs=bD.getBlobs();
		println("i: "+roomBlobs.size());
		areas=new Area[nX][nY];
		
		roomblobsGraphics.beginDraw();
		roomblobsGraphics.noStroke();
		Vector<Area>areaList=new Vector<Area>();
		for (int i=0;i<roomBlobs.size();i++){
			roomblobsGraphics.fill(i+1);
			Area area=new Area();
			area.color=color(random(255),random(255),random(255));
			areaList.add(area);
			Blob blob=roomBlobs.get(i);
			Polygon2D.display(roomblobsGraphics, blob.getBorders());
		}
		/*Area outsideArea=new Area();
		areaList.add(outsideArea);
		for (int x=0;x<nX;x++){
			for (int y=0;y<nY;y++){
				int col=roomblobsGraphics.get(x, y);
				int b=(int)brightness(col);
				if (b>0){
				Area area=areaList.get(b-1);
				areas[x][y]=area;
				}
				if (border[x][y]>0){
					areas[x][y]=outsideArea;
				}
			}
		}*/
	
			
		
		DepthAnalyser2D dA=new DepthAnalyser2D();
		dA.calculateObjectDepth(areas);
		areas= dA.getDistribution();
	}
	
	public void draw(){
		
		
		
		float scaleW=width*0.25f*1f/nX;
		float scaleH=height*1f/nY;
		float scaleMin=min(scaleW,scaleH);
		scale(scaleMin,scaleMin);
		image(imgFloorplan,0,0);
		noStroke();
		translate(width*0.25f/scaleMin,0);
		fill(255,0,0);
		for (int x=0;x<gridAnalyse.length;x++){
			for (int y=0;y<gridAnalyse[x].length;y++){
				float b=gridAnalyse[x][y];
				if (gridAnalyse[x][y]<255){
					fill(255,0,0);
					rect(x,y,1,1);
				}
				if (invert[x][y]==255){
					fill(0);
					rect(x,y,1,1);
				}
			}
		}
		for (int i=0;i<outside.size();i++){
			Pixel cell=outside.get(i);
			fill(0,255,255);
			rect(cell.x,cell.y,1,1);
		}
		noFill();
		stroke(255,0,255);
		for (int i=0;i<blobs.size();i++){
			Blob blob=blobs.get(i);
			//Area area=areas.get(i);
			if (abs(Polygon2D.getArea(blob.getBorders()))<200){
				//fill(0,0,255);
			}
			else{
				noFill();
			}
			
			Polygon2D.display(g, blob.getBorders());
		}
		translate(width*0.25f/scaleMin,0);
		/*for (int x=0;x<nX;x++){
			for (int y=0;y<nY;y++){
				float b=rooms[x][y];
				if (b==0){
					fill(255,0,255);
					rect(x,y,1,1);
				}
			}
		}*/
		
		noStroke();
		for (int x=0;x<nX;x++){
			for (int y=0;y<nY;y++){
				Area area=(Area)areas[x][y];
				
				//fill(area.color);
				rect(x,y,1,1);
			}
		}
noFill();
		
		stroke(0,255,0);
		
		for (int i=0;i<roomBlobs.size();i++){
			Blob blob=roomBlobs.get(i);
			fill(i*255f/roomBlobs.size(),200,200);
			//Polygon.display(g, blob.getBorders());
		}
	}
public class Pixel{
	public Pixel(int x,int y){
		this.x=x;
		this.y=y;
	}
	float brightness;
	int x;
	int y;
	boolean checked; 
}
public class Area{
	int color;
}


}